﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Bamboo.Utils
{
    /// <summary>
    /// 并发批量运行进程，不确保执行顺序
    /// </summary>
    public class ProcessExecuteMulti
    {
        public class PEItem
        {
            public string Name;
            public IAsyncResult AsyncResult;
            public ProcessExecute Proc;
            public Exception Error;

            public void Execute()
            {
                try
                {
                    Proc.Run();
                }
                catch ( Exception ex )
                {
                    Error = ex;
                }
            }
        }

        public List<PEItem> Items = new List<PEItem>();

        /// <summary>
        /// 开始异步运行
        /// </summary>
        /// <param name="name"></param>
        /// <param name="proc"></param>
        public void BeginRun(string name, ProcessExecute proc)
        {
            var item = new PEItem();
            item.Name = name;
            item.Proc = proc;
            var action = new Action(item.Execute);
            item.AsyncResult = action.BeginInvoke(null, null);
            Items.Add(item);
        }

        public void WaitForAll(int timeoutSeconds)
        {
            var endTime = DateTime.Now.AddSeconds(timeoutSeconds);
            foreach (var item in Items)
            {
                var diff = endTime - DateTime.Now;
                int timeoutMs = (int)diff.TotalMilliseconds;
                if (timeoutMs <= 0)
                {
                    item.Error = new TimeoutException("超时时间已用尽，无法等待任务结束，名称：" + item.Name + "，超时时间：" + timeoutMs + "ms");
                    continue;
                }
                bool ret = item.AsyncResult.AsyncWaitHandle.WaitOne(timeoutMs);
                if (!ret)
                {
                    item.Error = new TimeoutException("等待任务结束超时，名称：" + item.Name + "，超时时间：" + timeoutMs + "ms");
                }
            }
        }
    }
}
